package com.arpa.oms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.domain.dto.PurchaseDto;
import com.arpa.oms.domain.dto.PurchaseItemDto;
import com.arpa.oms.domain.entity.*;
import com.arpa.oms.domain.enums.OrderStatusEnum;
import com.arpa.oms.domain.enums.PurchaseTypeEnum;
import com.arpa.oms.domain.vo.PurchaseItemVO;
import com.arpa.oms.domain.vo.PurchaseVo;
import com.arpa.oms.mapper.PurchaseMapper;
import com.arpa.oms.service.*;
import com.arpa.wms.cache.GoodsCache;
import com.arpa.wms.cache.GoodsUnitConversionCache;
import com.arpa.wms.cache.SupplierCache;
import com.arpa.wms.cache.WarehouseCache;
import com.arpa.wms.common.util.OrderIdGeneratorUtil;
import com.arpa.wms.domain.entity.*;
import com.arpa.wms.domain.enums.InboundStatusEnum;
import com.arpa.wms.domain.enums.ReceiveStatusEnum;
import com.arpa.wms.domain.enums.ReceiveTypeEnum;
import com.arpa.wms.service.IReceiveService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * OMS采购单 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-10-22
 */
@Log4j2(topic = "business")
@Service
public class PurchaseServiceImpl extends ServiceImpl<PurchaseMapper, Purchase> implements IPurchaseService {


    // XYTODO TODO 计算百分数，除以100时计算的常量    后期可统一放到公用文件中
    public static final BigDecimal DECIMAL100 = new BigDecimal("100");

    @Resource
    private PartyCache partyCache;
    @Resource
    private WarehouseCache warehouseCache;
    @Resource
    private SupplierCache supplierCache;
    @Resource
    private GoodsUnitConversionCache goodsUnitConversionCache;
    @Autowired
    @Lazy
    private OmsSettlementServiceImpl omsSettlementService;
    private final IPurchaseItemService purchaseItemService;


    private final IOmsInboundService inboundService;

    private final IOmsInboundItemService inboundItemService;

    private final IOmsInventoryService inventoryService;

    @Resource
    @Lazy
    private IReceiveService receiveService;

    @Autowired
    private GoodsCache goodsCache;

    public PurchaseServiceImpl(IPurchaseItemService purchaseItemService,
                               IOmsInboundService inboundService,
                               IOmsInboundItemService inboundItemService,
                               IOmsInventoryService inventoryService) {
        this.purchaseItemService = purchaseItemService;
        this.inboundService = inboundService;
        this.inboundItemService = inboundItemService;
        this.inventoryService = inventoryService;
    }


    /**
     * 查询列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<PurchaseVo> queryList(PurchaseDto dto) {

        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StrUtil.isNotEmpty(dto.getSortField())) {
            dto.setSortField(CommonUtil.camel2Underline(dto.getSortField()));
        }
        List<PurchaseVo> purchaseVos = baseMapper.queryList(dto);
        // 翻译
        purchaseVos.stream().forEach(e -> {
            e.setWarehouseName(warehouseCache.translate(e.getWarehouseCode()));
            e.setSupplierName(supplierCache.translate(e.getSupplierCode()));
        });
        return purchaseVos;
    }

    /**
     * 查询合计,包含总数
     *
     * @param dto
     * @return
     */
    @Override
    public PurchaseVo queryListSum(PurchaseDto dto) {
        PurchaseVo purchaseVo = baseMapper.queryListSum(dto);
        return purchaseVo;
    }

    /**
     * 通过code查询采购单详细信息
     *
     * @param code 采购单号
     * @return
     */
    @Override
    public PurchaseVo getByCode(String code) {
        PurchaseVo purchaseVo = new PurchaseVo();
        Purchase purchase = getOneByCode(code);
        purchaseVo.setWarehouseName(warehouseCache.translate(purchase.getWarehouseCode()));
        purchaseVo.setSupplierName(supplierCache.translate(purchase.getSupplierCode()));
        BeanUtil.copyProperties(purchase, purchaseVo, false);
        purchaseVo.getPurchaseItemList().forEach(r->{
            List<GoodsUnitConversion> goodsUnitConversions = goodsUnitConversionCache.get(r.getGoodsCode());
            r.setGoodsUnitConversionList(goodsUnitConversions);
        });
        return purchaseVo;
    }

    /**
     * 通过code查询采购单详细信息
     *
     * @param code 采购单号
     * @return
     */
    @Override
    public Purchase getOneByCode(String code) {
        Purchase purchase = getOne(new QueryWrapper<Purchase>().lambda().eq(Purchase::getCode, code));
        if (purchase != null) {
            List<PurchaseItem> purchaseItems = purchaseItemService.list(new QueryWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode, purchase.getCode()));
            purchase.setPurchaseItemList(purchaseItems);
            return purchase;
        }
        return null;
    }

    /**
     * 采购单作废
     *
     * @param code 采购单号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void annul(String code) {
        Purchase purchase = getOne(new QueryWrapper<Purchase>().lambda().eq(Purchase::getCode, code).in(Purchase::getStatus, OrderStatusEnum.NEWS, OrderStatusEnum.NO_PASS));
        if (purchase == null) {
            throw new ServiceException("采购单不存在或目前状态不允许作废");
        } else {
            purchase.setStatus(OrderStatusEnum.ANNUL);
            updateById(purchase);
        }

    }

    /**
     * 创建采购单
     *
     * @param purchase
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Purchase purchase) {

        //检查提交的是否有重复的明细
        CheckDuplicatedata(purchase);
        calcQuantity(purchase);
        if (StrUtil.isNotBlank(purchase.getCode())) {
            PurchaseVo check = getByCode(purchase.getCode());
            if (check.getCode()== null) {
                log.error("采购单保存失败：根据提供的【{}】没有查找到该采购单。", purchase.getCode());
                throw new ServiceException("当前采购单不存在");
            }
            //获取采购单信息
            if(purchase.getStatus().equals(OrderStatusEnum.PENDING)||purchase.getStatus().equals(OrderStatusEnum.PASS)){
                log.error("采购单保存失败：采购单【{}】当前状态为【{}】不能发起修改操作。",purchase.getCode(),purchase.getStatus());
                throw new ServiceException("采购单信息状态不满足保存条件");
            }
            purchase.setModifiedBy(UserUtil.getCode());
            purchase.setModifiedName(partyCache.translate(UserUtil.getCode()));
            purchase.setStatus(OrderStatusEnum.NEWS);
            //
            this.updateByCode(purchase);
            //清除原有所有明细
            purchaseItemService.remove(new QueryWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode, purchase.getCode()));

        }else{
            purchase.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.PO, "",UserUtil.getBranchCode()));
            purchase.setGroupCode(UserUtil.getBranchCode());
            purchase.setPurchaseType(PurchaseTypeEnum.NORMAL);
            purchase.setCreatedBy(UserUtil.getCode());
            purchase.setCreatedName(partyCache.translate(UserUtil.getCode()));
            purchase.setModifiedBy(UserUtil.getCode());
            purchase.setModifiedName(partyCache.translate(UserUtil.getCode()));
            purchase.setShipmentCode(UserUtil.getShipmentCompanyCode());
            purchase.setShipmentName(UserUtil.getShipmentCompanyName());
            //保存采购单
            save(purchase);
        }

        purchase.getPurchaseItemList().forEach(r -> {
            r.setCode(IdUtil.simpleUUID());
            r.setPurchaseCode(purchase.getCode());
            r.setCreatedBy(purchase.getCreatedBy());
            r.setCreatedName(purchase.getCreatedName());
            r.setModifiedBy(purchase.getModifiedBy());
            r.setModifiedName(purchase.getModifiedName());
        });

        //保存采购明细
        purchaseItemService.saveBatch(purchase.getPurchaseItemList());

    }

    /**
     * 提交采购单
     *
     * @param purchase
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(Purchase purchase) {

        //检查提交的是否有重复的明细
        CheckDuplicatedata(purchase);
        //计算采购单位
        calcQuantity(purchase);

       if (StrUtil.isNotBlank(purchase.getCode())) {
           PurchaseVo check = getByCode(purchase.getCode());
           if (check.getCode()== null) {
               log.error("采购单提交失败：根据提供的code没有查找到该采购单。", purchase.getCode(), check.getStatus());
               throw new ServiceException("当前采购单不存在");
           }
            //获取采购单信息
            if (!(check.getStatus().equals(OrderStatusEnum.NEWS)||check.getStatus().equals(OrderStatusEnum.NO_PASS))) {
                log.error("采购单提交失败：采购单【{}】当前状态为【{}】不能发起提交操作。", purchase.getCode(), check.getStatus());
                throw new ServiceException("采购单当前状态不能提交");
            }
            purchase.setModifiedBy(UserUtil.getCode());
            purchase.setModifiedName(partyCache.translate(UserUtil.getCode()));
            purchase.setStatus(OrderStatusEnum.PENDING);
            //
            this.updateByCode(purchase);
            //清除原有所有明细
            purchaseItemService.remove(new QueryWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode, purchase.getCode()));
        }else{
            purchase.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.PO, "",UserUtil.getBranchCode()));
            purchase.setGroupCode(UserUtil.getBranchCode());
            purchase.setPurchaseType(PurchaseTypeEnum.NORMAL);
            purchase.setCreatedBy(UserUtil.getCode());
            purchase.setStatus(OrderStatusEnum.PENDING);
            purchase.setCreatedName(partyCache.translate(UserUtil.getCode()));
            purchase.setModifiedBy(UserUtil.getCode());
            purchase.setModifiedName(partyCache.translate(UserUtil.getCode()));
            save(purchase);
        }

         purchase.getPurchaseItemList().forEach(r -> {
                r.setCode(IdUtil.simpleUUID());
                r.setPurchaseCode(purchase.getCode());
                r.setCreatedBy(purchase.getCreatedBy());
                r.setCreatedName(purchase.getCreatedName());
                r.setModifiedBy(purchase.getModifiedBy());
                r.setModifiedName(purchase.getModifiedName());
            });
            //保存采购明细
            purchaseItemService.saveBatch(purchase.getPurchaseItemList());
    }





    /**
     * 采购单审核
     *
     * @param code    采购单号
     * @param status  审核结果
     * @param opinion 审核意见
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void verify(String code, String status, String opinion) {
        //获取采购单信息
        PurchaseVo purchase = getByCode(code);
        if (purchase == null) {
            log.info("采购单审核失败：采购单【{}】找不到",code);
            throw new ServiceException("找不到采购单信息");
        }
        if(!purchase.getStatus().equals(OrderStatusEnum.PENDING)){
            log.error("采购单审核失败：采购单【{}】当前状态为【{}】不能发起审核操作。",purchase.getCode(),purchase.getStatus());
            throw new ServiceException("采购单审核失败：采购单【"+purchase.getCode()+"】当前状态为【"+purchase.getStatus()+"】不能发起审核操作。" );
        }
        switch (status) {
            case "PASS": {
                if(purchase.getStatus().equals(OrderStatusEnum.PASS)){
                    log.error("采购单审核失败：采购单【{}】当前状态为【{}】不能发起审核操作。",purchase.getCode(),purchase.getStatus());
                    throw new ServiceException("采购单已审核通过");
                }
                //判断仓库是否启用库位管理
                Map<String, Object> warehouseMap = warehouseCache.get(purchase.getWarehouseCode());
                if (MapUtil.isEmpty(warehouseMap)) {
                    log.error("采购单审核失败：采购单【{}】所属仓库【{}】找不到。",purchase.getCode(),purchase.getWarehouseCode());
                    throw new ServiceException("找不到仓库信息");
                }
                Warehouse warehouse = BeanUtil.mapToBean(warehouseMap, Warehouse.class, false);
                //更新采购单审核结果
                update(new UpdateWrapper<Purchase>().lambda()
                        .eq(Purchase::getCode, code)
                        .set(Purchase::getStatus, OrderStatusEnum.PASS)
                        .set(Purchase::getVerifyOpinion, opinion)
                        .set(Purchase::getGmtVerify, LocalDateTime.now())
                        .set(Purchase::getVerifyBy, UserUtil.getCode())
                        .set(Purchase::getVerifyName, partyCache.translate(UserUtil.getCode())));
                //启用库位管理:0不启用，1启用
                Integer locationManagement = warehouse.getLocationManagement();
                if (ObjectUtil.isNull(locationManagement)) {
                    throw new ServiceException("仓库没有维护“启用库位管理”");
                }
                //未启用：直接生成OMS采购入库单，生成OMS库存
                if (locationManagement == 0) {
                    //生成入库单
                    OmsInbound omsInbound = new OmsInbound();
                    BeanUtils.copyProperties(purchase, omsInbound);
                    omsInbound.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.RK, "",UserUtil.getBranchCode()));
                    omsInbound.setShipmentCode(purchase.getShipmentCode());
                    omsInbound.setShipmentName(purchase.getShipmentName());
                    omsInbound.setWarehouseCode(purchase.getWarehouseCode());
                    omsInbound.setSourceCode(purchase.getCode());
                    omsInbound.setOwedAmount(purchase.getOwedAmount());
                    omsInbound.setPaymentAmount(purchase.getPaymentAmount());
                    omsInbound.setType(PurchaseTypeEnum.NORMAL.getValue());
                    omsInbound.setCreatedBy(UserUtil.getCode());
                    omsInbound.setCreatedName(partyCache.translate(UserUtil.getCode()));
                    omsInbound.setModifiedBy(UserUtil.getCode());
                    omsInbound.setModifiedName(partyCache.translate(UserUtil.getCode()));
                    omsInbound.setStatus(InboundStatusEnum.FINISH_IN.getValue());
                    //保存入库单
                    inboundService.save(omsInbound);
                    List<OmsInboundItem> inboundItems = purchase.getPurchaseItemList().stream().map(r -> {
                        OmsInboundItem item = new OmsInboundItem();
                        BeanUtil.copyProperties(r, item, false);
                        item.setCode(IdUtil.simpleUUID());
                        item.setInboundCode(omsInbound.getCode());
                        item.setStorageQuantity(r.getPlanBasicQuantity());
                        item.setCreatedBy(UserUtil.getCode());
                        item.setCreatedName(partyCache.translate(UserUtil.getCode()));
                        item.setModifiedBy(UserUtil.getCode());
                        item.setModifiedName(partyCache.translate(UserUtil.getCode()));
                        return item;
                    }).collect(Collectors.toList());
                    //保存入库单明细
                    inboundItemService.saveBatch(inboundItems);
                    inboundItems.forEach(r -> {
                        OmsInventory inventory = inventoryService.getOne(new QueryWrapper<OmsInventory>().lambda().eq(OmsInventory::getGoodsCode, r.getGoodsCode())
                                .eq(OmsInventory::getWarehouseCode,omsInbound.getWarehouseCode())
                                .eq(OmsInventory::getShipmentCode,omsInbound.getShipmentCode()));
                        if (inventory != null) {
                            //更新库存
                            inventoryService.update(new UpdateWrapper<OmsInventory>().lambda()
                                    .eq(OmsInventory::getGoodsCode, r.getGoodsCode()).eq(OmsInventory::getWarehouseCode,omsInbound.getWarehouseCode())
                                    .eq(OmsInventory::getShipmentCode,omsInbound.getShipmentCode())
                                    .setSql("quantity=quantity+" + r.getStorageQuantity())
                                    .setSql("average_unit_price = (total_amount+"+r.getTotalMoney()+")/quantity")
                                    .setSql("total_amount = average_unit_price * quantity"));
                        } else {
                            //新增
                            inventory = new OmsInventory();
                            BeanUtil.copyProperties(r, inventory, false);
                            inventory.setShipmentCode(purchase.getShipmentCode());
                            inventory.setShipmentName(purchase.getShipmentName());
                            inventory.setWarehouseCode(purchase.getWarehouseCode());
                            inventory.setCode(IdUtil.simpleUUID());
                            inventory.setQuantity(r.getStorageQuantity());
                            inventory.setAverageUnitPrice(r.getTotalMoney().divide(r.getStorageQuantity()));
                            inventory.setTotalAmount(r.getTotalMoney());
                            inventory.setCreatedBy(UserUtil.getCode());
                            inventory.setCreatedName(partyCache.translate(UserUtil.getCode()));
                            inventory.setModifiedBy(UserUtil.getCode());
                            inventory.setCreatedName(partyCache.translate(UserUtil.getCode()));
                            inventoryService.save(inventory);
                        }
                    });
                    //更新采购单明细实际采购数量，入库数量，合计金额
                    purchase.getPurchaseItemList().forEach(r -> {
                        //根据实际采购数量计算入库数量
                        BigDecimal storageQuantity = r.getPlanQuantity().multiply(r.getUnitConvertQuantity());
                        //根据实际采购数量计算税额
                        BigDecimal taxMoney = r.getPlanQuantity().multiply(r.getTaxUnitPrice());
                        //根据实际采购数量计算金额
                        BigDecimal amountMoney = r.getPlanQuantity().multiply(r.getUnitPrice());
                        //根据实际采购数量计算价税合计
                        BigDecimal totalMoney = r.getPlanQuantity().multiply(r.getTaxUnitPrice());
                        purchaseItemService.update(new UpdateWrapper<PurchaseItem>().lambda()
                                .eq(PurchaseItem::getCode, r.getCode())
                                .set(PurchaseItem::getTaxMoney, taxMoney)
                                .set(PurchaseItem::getAmountMoney,amountMoney)
                                .set(PurchaseItem::getTotalMoney,totalMoney)
                                .set(PurchaseItem::getActualQuantity, r.getPlanQuantity())
                                .set(PurchaseItem::getActualBasicQuantity, r.getPlanBasicQuantity())
                                .set(PurchaseItem::getStorageQuantity, storageQuantity)
                        );

                    });
                    //通过查询采购明细表获取实际采购数量
                    double actualQuantity = baseMapper.getPurchaseActualQuantity(purchase.getCode());
                    double actualBasicQuantity = baseMapper.getPurchaseActualBaiscQuantity(purchase.getCode());
                    //更新采购单实际采购数量
                    update(new UpdateWrapper<Purchase>().lambda()
                            .eq(Purchase::getCode, code)
                            .set(Purchase::getActualQuantity, actualQuantity)
                            .set(Purchase::getActualBasicQuantity, actualBasicQuantity)
                            .set(Purchase::getModifiedBy, UserUtil.getCode())
                            .set(Purchase::getModifiedName, partyCache.translate(UserUtil.getCode()))
                    );



                    omsSettlementService.generatePayment(omsInbound);

                } else {
                    //启用：生成WMS收货单F
                    Receive receive = new Receive();
                    BeanUtils.copyProperties(purchase, receive);
                    receive.setCode(OrderIdGeneratorUtil.generatorOrderId(OrderIdGeneratorUtil.OrderTypeEnum.SH, "",UserUtil.getBranchCode()));
                    receive.setGroupCode(warehouse.getGroupCode());
                    receive.setType(ReceiveTypeEnum.RECEIVE.getValue());
                    receive.setWarehouseCode(purchase.getWarehouseCode());
                    receive.setIssue(0);
                    receive.setIsOmsOrder(1);
                    receive.setSupplierCode(purchase.getSupplierCode());
                    receive.setStatus(ReceiveStatusEnum.WAITING_RECEIVE.getValue());
                    receive.setSourceCode(purchase.getCode());
                    receive.setGmtPlanArrival(purchase.getGmtPlanArrival());
                    receive.setTotalQuantity(purchase.getPlanQuantity());
                    receive.setCreatedBy(UserUtil.getCode());
                    receive.setCreatedName(partyCache.translate(UserUtil.getCode()));
                    receive.setModifiedBy(UserUtil.getCode());
                    receive.setModifiedName(partyCache.translate(UserUtil.getCode()));
                    List<ReceiveItem> receiveItems = purchase.getPurchaseItemList().stream().map(r -> {
                        ReceiveItem item = new ReceiveItem();
                        BeanUtil.copyProperties(r, item, false);
                        item.setSourceItemCode(r.getCode());
                        item.setCode(IdUtil.simpleUUID());
                        item.setReceiveCode(receive.getCode());
                        item.setGoodsUnit(r.getPurchaseUnit());
                        item.setGoodsUnitName(r.getPurchaseUnitName());
                        item.setCreatedBy(UserUtil.getCode());
                        item.setCreatedName(partyCache.translate(UserUtil.getCode()));
                        item.setModifiedBy(UserUtil.getCode());
                        item.setModifiedName(partyCache.translate(UserUtil.getCode()));
                        return item;
                    }).collect(Collectors.toList());
                    receive.setReceiveItemList(receiveItems);
                    receiveService.save(receive);
                }
                break;
            }
            default: {
                update(new UpdateWrapper<Purchase>().lambda()
                        .eq(Purchase::getCode, code)
                        .set(Purchase::getStatus, OrderStatusEnum.NO_PASS)
                        .set(Purchase::getVerifyOpinion, opinion)
                        .set(Purchase::getGmtVerify, LocalDateTime.now())
                        .set(Purchase::getVerifyBy, UserUtil.getCode())
                        .set(Purchase::getVerifyName, partyCache.translate(UserUtil.getCode())));
                break;
            }
        }
    }


    public void calcQuantity(Purchase entity) {
        // 计算订单总数（销售单位、基本单位）
        BigDecimal planQuantity = BigDecimal.ZERO, planBasicQuantity = BigDecimal.ZERO;
        BigDecimal purchaseTotalMoney =BigDecimal.ZERO;
        Goods goods;
        Integer unitPrecision;
        for(PurchaseItem e: entity.getPurchaseItemList()){

            goods = goodsCache.getObj(e.getGoodsCode());
            if (ObjectUtil.isNull(goods)) {
                throw new ServiceException("商品【" + e.getGoodsName() + "】信息不存在");
            }
            // 处理商品数量精度
            unitPrecision = goods.getUnitPrecision().intValue();
            e.setPlanBasicQuantity(e.getPlanQuantity().multiply(e.getUnitConvertQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP));

            // 含税单价 = 单价*税率/100

            e.setTaxUnitPrice(e.getUnitPrice().multiply(e.getTaxRate()).divide(DECIMAL100).add(e.getUnitPrice()).setScale(6, BigDecimal.ROUND_HALF_UP));
            // 金额 = 单价*销售数量
            e.setAmountMoney(e.getUnitPrice().multiply(e.getPlanQuantity()).setScale(6, BigDecimal.ROUND_HALF_UP));

            // 税额 = 单价*销售数量*税率/100  保留6位小数
            e.setTaxMoney(e.getUnitPrice().multiply(e.getPlanQuantity()).multiply(e.getTaxRate()).divide(DECIMAL100).setScale(6, BigDecimal.ROUND_HALF_UP));
            // 价税合计 = 金额 + 税额 ; 重新再计算一遍，避免前面保留小数位数造成精度丢失
            e.setTotalMoney(e.getUnitPrice().multiply(e.getPlanQuantity()).add(
                    e.getUnitPrice().multiply(e.getPlanQuantity()).multiply(e.getTaxRate()).divide(DECIMAL100)
            ).setScale(6, BigDecimal.ROUND_HALF_UP));

            // 计算计划总量
            planQuantity = planQuantity.add(e.getPlanQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP);
            planBasicQuantity = planBasicQuantity.add(e.getPlanBasicQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP);
            purchaseTotalMoney=purchaseTotalMoney.add(e.getTotalMoney()).setScale(6, BigDecimal.ROUND_HALF_UP);
        }
        //计算采购单实际欠款
        BigDecimal owedAmount = purchaseTotalMoney.subtract(entity.getPaymentAmount());
        entity.setOwedAmount(owedAmount);
        entity.setPlanQuantity(planQuantity);
        entity.setPlanBasicQuantity(planBasicQuantity);
    }





    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(Purchase entity) {
        if(StringUtils.isBlank(entity.getModifiedBy())){
            entity.setModifiedBy(UserUtil.getCode());
        }
        return baseMapper.update(entity,new QueryWrapper<Purchase>().lambda().eq(Purchase::getCode,entity.getCode()));
    }



    public  void CheckDuplicatedata(Purchase purchase){
        List<PurchaseItem> purchaseItemList = purchase.getPurchaseItemList();
        Map<String, Object> validDuplication = new HashMap<>();
        String validKey;
        for (PurchaseItem e:purchaseItemList) {
            validKey = e.getGoodCode() + "-" + e.getBasicUnit();
            if(validDuplication.containsKey(validKey)){
                throw new ServiceException("存在重复的商品信息，请确认");
            }else{
                validDuplication.put(validKey, e);
            }
        }
    }


    @Override
    public List<Purchase> findCanRefundList(PurchaseDto dto) {
        // 根据"实际采购数量 - 退货数量 > 0" 来判断
        List<Purchase> purchaseVos= list(new QueryWrapper<Purchase>().lambda().eq(Purchase::getShipmentCode, dto.getShipmentCode())
                .eq(Purchase::getWarehouseCode, dto.getWarehouseCode()).eq(Purchase::getSupplierCode, dto.getSupplierCode())
                .apply(" actual_basic_quantity - refund_basic_quantity > 0 "));
        return purchaseVos;
    }

    @Override
    public List<PurchaseItemVO> findCanRefundItemList(PurchaseItemDto dto) {
        if (StrUtil.isBlank(dto.getPurchaseCode())) {
            throw new ServiceException("采购单号为空");
        }
        List<PurchaseItemVO> purchaseItemVOList =purchaseItemService.findCanRefundItemList(dto);
        if (IterUtil.isNotEmpty(purchaseItemVOList)) {
            // 过滤掉实际数量 - 可退数量 = 0 的
            purchaseItemVOList = purchaseItemVOList.stream().filter(e->{
                return e.getActualBasicQuantity().subtract(e.getRefundBasicQuantity()).compareTo(BigDecimal.ZERO) > 0;
            }).collect(Collectors.toList());
            // 计算可退数量
            purchaseItemVOList.forEach(e->{
                e.setRefundableQuantity(e.getActualQuantity().subtract(e.getRefundQuantity()));
            });
            return purchaseItemVOList;
        }

        return null;
    }

}
